<ng-container *ngIf="virtual else default">
  <cdk-virtual-scroll-viewport [itemSize]="itemSize">
    <ul class="ti3-tree-container ti3-tree-parent-node" [id]="appendId('list')">
      <ng-container *cdkVirtualFor="let node of getFlatData(data); index as i;">
        <li
          class="ti3-tree-virtual-scroll-node"
          [ngClass]="{'ti3-tree-leaf-node': !isRootNode(node), 'ti3-tree-virtual-scroll-first-child-node': node.isFirst}"
          [ngStyle]="{'marginLeft': getNodeLeftSpace(node)}"
        >
          <ng-container *ngTemplateOutlet="virtualScrollTreeItem; context: {$implicit: node, index: i}"></ng-container>
        </li>
      </ng-container>
    </ul>
  </cdk-virtual-scroll-viewport>
</ng-container>
<ng-template #default>
  <ul class="ti3-tree-container ti3-tree-parent-node" [id]="appendId('list')">
    <li *ngFor="let node of data; index as i;">
      <ng-container *ngTemplateOutlet="treeItem; context: {$implicit: node, index: i}"></ng-container>
    </li>
  </ul>
</ng-template>

<ng-template #treeItem let-node let-i="index">
  <div
    class="ti3-tree-content-box"
    [id]="appendId(i + '_node')"
    [ngClass]="{'ti3-tree-item-leaf': isLeaf(node), 'ti3-tree-content-box-disabled': node.disabled}"
  >
    <span class="ti3-tree-item-guide-line"></span>
    <ti-loading *ngIf="node.loadStatus === 'loading'" class="ti3-tree-item-loading"></ti-loading>
    <i
      (click)="onClickPnodeIcon(node, $event)"
      *ngIf="!node.loadStatus || node.loadStatus !== 'loading'"
      [id]="appendId(i + '_icon')"
      class="ti3-icon"
      [ngClass]="{'ti3-icon-minus-square': !isLeaf(node) && node.expanded,
                        'ti3-icon-plus-square': !isLeaf(node) && !node.expanded}"
    >
    </i>
    <label class="ti3-tree-checkbox-wrapper" *ngIf="multiple">
      <input
        type="checkbox"
        [(ngModel)]="node.checked"
        [disabled]="node.disabled"
        *ngIf="showCheckboxFn(node)"
        [id]="appendId('checkbox_' + i)"
        [indeterminate]="node.checked === 'indeterminate'"
        (change)="onInputChange(node, $event)"
        tabindex="-1"
        tiCheckbox
      />
    </label>
    <div
      (click)="onItemWrapperClick(node)"
      [id]="appendId(i + '_content')"
      class="ti3-tree-node-text-wrapper"
      #nodeList
      (keydown)="onKeydown($event, node)"
      (blur)="onBlur(node)"
      (focus)="onFocus(node)"
      [tabindex]="node.disabled ? -1 : 0"
      [draggable]="isDraggable(node)"
      (dragstart)="onDragstart($event, node)"
      (dragenter)="onDragenter($event, node)"
      (dragover)="onDragover($event, node)"
      (dragleave)="onDragleave($event, node)"
      (drop)="onDrop($event, node)"
      (dragend)="onDragend($event, node)"
      (mouseenter)="onMousenode(node, 'enter')"
      (mouseleave)="onMousenode(node, 'leave')"
      [ngClass]="{'ti3-tree-item-active' : actived === node,
                    'ti3-tree-text-disabled-wrapper': node.disabled,
                    'ti3-tree-text-nomultiple-wrapper': !multiple && !isLeaf(node),
                    'ti3-tree-text-multiple-leaf-wrapper': multiple && isLeaf(node),
                    'ti3-tree-text-leaf-wrapper': !multiple && isLeaf(node),
                    'ti3-tree-text-focus': node.focused,
                    'ti3-tree-content-drag-box': nodeDraggable}"
    >
      <ng-container *ngIf="itemTemplate else labelTemplate">
        <ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: node, index: i}"> </ng-container>
      </ng-container>
      <ng-template #labelTemplate>
        <ng-container>
          <i class="{{getItemIcon(node)}}" *ngIf="node.expandIcon || node.collapseIcon"></i>
          <span
            [title]="node.label"
            *ngIf="!node.editing"
            class="ti3-tree-node-text"
            [innerHTML]="node.label | tiHighlight: highlightWords"
          ></span>
          <input
            tiText
            tiValidation
            tiRequired
            tiAutoSelect
            autofocus
            *ngIf="node.editing"
            autocomplete="off"
            class="ti3-tree-edit-input"
            [id]="appendId(i + '_input')"
            (blur)="onBlurEdit(node)"
            (keydown)="onKeydownEdit($event)"
            [(ngModel)]="node.label"
            (keyup.enter)="onBlurEdit(node)"
          />
          <ng-container *ngIf="node.isHover && !node.disabled">
            <ti-icon
              name="add1"
              *ngIf="node.addable"
              [id]="appendId(i + '_add')"
              (click)="addNode($event, node)"
              [title]="treeLan.create"
              class="ti3-tree-operate"
            ></ti-icon>
            <ti-icon
              name="edit"
              *ngIf="node.editable"
              [id]="appendId(i + '_edit')"
              (click)="editNode($event, node)"
              [title]="treeLan.edit"
              class="ti3-tree-operate"
            ></ti-icon>
            <ti-icon
              name="delete-1"
              *ngIf="node.deleteable"
              [id]="appendId(i + '_delete')"
              (click)="deleteNode($event,node)"
              [title]="treeLan.delete"
              class="ti3-tree-operate"
            ></ti-icon>
          </ng-container>
        </ng-container>
      </ng-template>
    </div>
  </div>
  <ul *ngIf="!isLeaf(node) && node.expanded" class="ti3-tree-parent-node" [id]="appendId('child_list_' + i)">
    <li class="ti3-tree-leaf-node" *ngFor="let children of node.children; index as j; trackBy: trackByFn">
      <ng-container *ngTemplateOutlet="treeItem; context: {$implicit: children, index: i + '_' + j}"></ng-container>
    </li>
    <ng-container *ngIf="node.showMore">
      <ng-container *ngTemplateOutlet="moreTempalte; context: {$implicit: node, index: i}"> </ng-container>
    </ng-container>

    <ng-container *ngIf="node.loadStatus === 'error'">
      <li class="ti3-tree-leaf-node">
        <div class="ti3-tree-content-box">
          <span class="ti3-tree-item-guide-line"></span>
          <ti-loadingfail (reload)="onClickReload($event, node)"></ti-loadingfail>
        </div>
      </li>
    </ng-container>
  </ul>
</ng-template>
<ng-template #moreTempalte let-node let-i="index">
  <li class="ti3-tree-leaf-node">
    <ti-loading *ngIf="node.moreStatus === 'loading'" class="ti3-tree-more-loading"></ti-loading>
    <div
      class="ti3-tree-content-box ti3-tree-item-leaf ti3-tree-more-content"
      [ngClass]="{'ti3-tree-more-box': node.moreStatus === 'loading',
                    'ti3-tree-more-error': node.moreStatus === 'error'}"
    >
      <span class="ti3-tree-item-guide-line"></span>
      <ng-container *ngIf="(node.moreStatus !== 'error') else moreErrorTemplate">
        <section (click)="onClickMore(node)" [id]="appendId(i + '_more')" class="ti3-tree-node-more-text">{{treeLan.more}}</section>
      </ng-container>
      <ng-template #moreErrorTemplate>
        <ti-loadingfail (reload)="onClickMore(node)"></ti-loadingfail>
      </ng-template>
    </div>
  </li>
</ng-template>

<ng-template #virtualScrollTreeItem let-node let-i="index">
  <div
    class="ti3-tree-content-box"
    [id]="appendId(i + '_node')"
    [ngClass]="{'ti3-tree-item-leaf': isLeaf(node), 'ti3-tree-content-box-disabled': node.disabled}"
  >
    <span *ngIf="!isRootNode(node)" class="ti3-tree-item-guide-line"></span>
    <span
      *ngFor="let item of getVerticalGuideLines(node.level); index as j;"
      class="ti3-tree-item-vertical-guide-line"
      [ngClass]="{'ti3-tree-last-item-vertical-guide-line': node.isLast && j === 0}"
      [ngStyle]="{'left': getVerticalGuideLineLeft(j)}"
    ></span>
    <ti-loading *ngIf="node.loadStatus === 'loading'" class="ti3-tree-item-loading"></ti-loading>
    <i
      (click)="onClickPnodeIcon(node, $event)"
      *ngIf="!node.loadStatus || node.loadStatus !== 'loading'"
      [id]="appendId(i + '_icon')"
      class="ti3-icon"
      [ngClass]="{'ti3-icon-minus-square': !isLeaf(node) && node.expanded,
                        'ti3-icon-plus-square': !isLeaf(node) && !node.expanded}"
    >
    </i>
    <label class="ti3-tree-checkbox-wrapper" *ngIf="multiple">
      <input
        type="checkbox"
        [(ngModel)]="node.checked"
        [disabled]="node.disabled"
        *ngIf="showCheckboxFn(node)"
        [id]="appendId('checkbox_' + i)"
        [indeterminate]="node.checked === 'indeterminate'"
        (change)="onInputChange(node, $event)"
        tabindex="-1"
        tiCheckbox
      />
    </label>
    <div
      (click)="onItemWrapperClick(node)"
      [id]="appendId(i + '_content')"
      class="ti3-tree-node-text-wrapper"
      #nodeList
      (keydown)="onKeydown($event, node)"
      (blur)="onBlur(node)"
      (focus)="onFocus(node)"
      [tabindex]="node.disabled ? -1 : 0"
      [draggable]="isDraggable(node)"
      (dragstart)="onDragstart($event, node)"
      (dragenter)="onDragenter($event, node)"
      (dragover)="onDragover($event, node)"
      (dragleave)="onDragleave($event, node)"
      (drop)="onDrop($event, node)"
      (dragend)="onDragend($event, node)"
      (mouseenter)="onMousenode(node, 'enter')"
      (mouseleave)="onMousenode(node, 'leave')"
      [ngClass]="{'ti3-tree-item-active' : actived === node,
                    'ti3-tree-text-disabled-wrapper': node.disabled,
                    'ti3-tree-text-nomultiple-wrapper': !multiple && !isLeaf(node),
                    'ti3-tree-text-multiple-leaf-wrapper': multiple && isLeaf(node),
                    'ti3-tree-text-leaf-wrapper': !multiple && isLeaf(node),
                    'ti3-tree-text-focus': node.focused,
                    'ti3-tree-content-drag-box': nodeDraggable}"
    >
      <ng-container *ngIf="itemTemplate else labelTemplate">
        <ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: node, index: i}"> </ng-container>
      </ng-container>
      <ng-template #labelTemplate>
        <ng-container>
          <i class="{{getItemIcon(node)}}" *ngIf="node.expandIcon || node.collapseIcon"></i>
          <span
            [title]="node.label"
            *ngIf="!node.editing"
            class="ti3-tree-node-text"
            [innerHTML]="node.label | tiHighlight: highlightWords"
          ></span>
          <input
            tiText
            tiValidation
            tiRequired
            tiAutoSelect
            autofocus
            *ngIf="node.editing"
            autocomplete="off"
            class="ti3-tree-edit-input"
            [id]="appendId(i + '_input')"
            (blur)="onBlurEdit(node)"
            (keydown)="onKeydownEdit($event)"
            [(ngModel)]="node.label"
            (keyup.enter)="onBlurEdit(node)"
          />
          <ng-container *ngIf="node.isHover && !node.disabled">
            <ti-icon
              name="add1"
              *ngIf="node.addable"
              [id]="appendId(i + '_add')"
              (click)="addNode($event, node)"
              [title]="treeLan.create"
              class="ti3-tree-operate"
            ></ti-icon>
            <ti-icon
              name="edit"
              *ngIf="node.editable"
              [id]="appendId(i + '_edit')"
              (click)="editNode($event, node)"
              [title]="treeLan.edit"
              class="ti3-tree-operate"
            ></ti-icon>
            <ti-icon
              name="delete-1"
              *ngIf="node.deleteable"
              [id]="appendId(i + '_delete')"
              (click)="deleteNode($event,node)"
              [title]="treeLan.delete"
              class="ti3-tree-operate"
            ></ti-icon>
          </ng-container>
        </ng-container>
      </ng-template>
    </div>
  </div>
</ng-template>
